package bebGraphical;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.TextField;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.Random;
import java.util.Vector;

import bebDialogs.*;

public class Ordi extends Panel implements MouseListener,KeyListener,FocusListener{
	private static char nameSet='A';
	private static int ORDI_W=100;
	private static int ORDI_H=100;
    
	static int collisionLength=1;
	static int packLength=1;
	static int interLength=0;
	/*
	 * ce boolean permet de distinguer deux cas 
	 * d'exécution un exercice saisi par l'utilisateur 
	 * ou une simulation normale 
	 * 
	 */
	static boolean exercice=false;
	
	
	
	int N=0;
	int bo=0;
	int bornSup = (int) (Math.pow(2, Math.min(N, 10))-1);
	
	int remainingSlots=0;
	int remainingPackets=0;
	
	String ordiName;
	
	boolean sending=false;
	boolean crash=false;
	/*
	 * afin d'assurer que l'utilisateur ne tape 
	 * dans la zone texte que des chiffres 
	 * on utilise les regx
	 */
	
	/*
	 * composants graphiquespermettant de 
	 * stabiliser l'affichage 
	 */
	
	/*
	 * [-1]
	 */
	Color normalBgColor=Color.lightGray;//new Color(186,174,225);
	Color crashBgColor=new Color(255, 128, 128);
	Color sendingBgColor=new Color(128, 255, 128);
	
	/*
	 * [0]
	 */
	Label oNameLabel=new Label();
	/*
	 * [1]
	 */
	
	Label packetsLabel=new Label();
	TextField packetsTextField=new TextField();
	TextField backoffTextField=new TextField();
	
	/*
	 * [2]
	 */
	Label backoffLabel=new Label();
	/*
	 * [3]
	 */
	Label intervalLabel=new Label();
	/*
	 * [4]
	 */
	Label collisionLabel=new Label();
	
	
	/*
	 * le vecteur suivant conserve des pt de restoration 
	 * 
	 */
	
	Vector<RestorationPoint> restorePoints=new Vector<RestorationPoint>();
/*
 * en haut les attributs en bas les méthodes 
 */
	private static final long serialVersionUID = 1L;
	
	
	public Ordi() {
		
		
		ordiName=""+nameSet;
		this.setBackground(normalBgColor);
	    this.setPreferredSize(new Dimension(ORDI_W, ORDI_H));
		nameSet++;
		
		/*
		 * ajouter les composants graphiques 
		 */
		
		this.setLayout(new GridBagLayout());
		
		GridBagConstraints c=new GridBagConstraints();
		c.weighty=1.1;
		
		c.gridx=0;
		c.gridy=0;
		c.anchor=GridBagConstraints.LINE_START;
		
		c.gridwidth=2;
		c.gridheight=1;
		
	
	
		
		/*
		 * [0]
		 */
		
		oNameLabel.setText("[StationID]$ "+ordiName);
		
		this.add(oNameLabel,c);
		
		/*
		 * [1]
		 */
		c.gridy=1;
		c.gridwidth=1;
		
		packetsLabel.setText("[Pcks]$ ");
		
		
		
		this.add(packetsLabel,c);
		
		c.gridx=1;
		
		this.add(packetsTextField,c);
		c.gridx=0;
		
		c.gridwidth=2;
		
		/*
		 * [2]
		 */
		c.gridy=2;
		
		intervalLabel.setText("[Interval]$ N / P");
		
		this.add(intervalLabel,c);
		

		/*
		 * [3]
		 */
		c.gridy=3;
		backoffLabel.setText("[BkOff]$ ");
		
		
		
		this.add(backoffLabel,c);
		

		c.gridx=1;
		
		this.add(backoffTextField,c);
		c.gridx=0;
		c.gridwidth=2;
		
		/*
		 * [4]
		 */
		c.gridy=4;
		
		collisionLabel.setText("[Collisions]$ "+N);
		
		
		this.add(collisionLabel,c);
		
		packetsTextField.addKeyListener(this);
		backoffTextField.addKeyListener(this);
		packetsTextField.addFocusListener(this);
		backoffTextField.addFocusListener(this);

		this.addMouseListener(this);
		oNameLabel.addMouseListener(this);
		packetsLabel.addMouseListener(this);
		backoffLabel.addMouseListener(this);
		intervalLabel.addMouseListener(this);
		collisionLabel.addMouseListener(this);
		
		
	}
	
	@Override
	public void paint(Graphics g) {
	
	oNameLabel.setText("[StationID]$ "+ordiName);
		 
	packetsTextField.setText(""+remainingPackets);
	
	backoffTextField.setText(""+bo);
	
	/*
	 * N==0 ==> un intervalle de la forme [0..0] ce qui est réduit à un point
	 * et dont l'affichage n'est pas porteur d'information donc on affiche N/P
	 * pour dore indéterminé ou pas encore utilisé
	 * 
	 */
	
	if(bornSup==0){
		intervalLabel.setText("[Interval]$ N / P");
	}else {
		intervalLabel.setText("[Interval]$ [0.."+bornSup+"]");	
	}
	
	collisionLabel.setText("[Collisions]$ "+N);
	
	if(crash){
	this.setBackground(crashBgColor);	
	}else {
		if(sending ){
		this.setBackground(sendingBgColor);	
		}else{
		this.setBackground(normalBgColor);	
		}
		
	}
	
	}

	public void setSending(boolean sending) {
		this.sending = sending;
		this.repaint();
	}

	public void setEditable(boolean b){
		packetsTextField.setEditable(b);
		backoffTextField.setEditable(b);
	}
	
	@Override
	public void setBackground(Color bgColor) {
		
		oNameLabel.setBackground(bgColor);
		packetsLabel.setBackground(bgColor);
		backoffLabel.setBackground(bgColor);
		intervalLabel.setBackground(bgColor);
		collisionLabel.setBackground(bgColor);
		super.setBackground(bgColor);
	}
	
	public void createRestorationPoint(int n){
		RestorationPoint r=new RestorationPoint(N, bo, bornSup, remainingPackets, crash,sending, n);
		restorePoints.add(r);
	}
	
	public void applyRestorationPoint(int n){
		for(int i=0;i<restorePoints.size();i++){
			if(restorePoints.elementAt(i).getRestorationPointNum()==n){
				this.N=restorePoints.elementAt(i).getN();
				this.bo=restorePoints.elementAt(i).getBo();
				this.bornSup=restorePoints.elementAt(i).getBornSup();
				this.crash=restorePoints.elementAt(i).isCrash();
				this.sending=restorePoints.elementAt(i).isSending();
				this.remainingPackets=restorePoints.elementAt(i).getRemainingPackets();
				this.repaint();
				break;
			}
		}
	}
	
	public int getRemainingSlots() {
		return remainingSlots;
	}
	
	public static int getPackLength() {
		return packLength;
	}
	
	public static int getCollisionLength() {
		return collisionLength;
	}
	
	public static void setPackLength(int packLength) {
		Ordi.packLength = packLength+1;
	}
	
	public static void setCollisionLength(int collisionLength) {
		Ordi.collisionLength = collisionLength+1;
	}
	
	public static int getInterLength() {
		return interLength;
	}

	public static void setInterLength(int interLength) {
		Ordi.interLength = interLength;
	}

	public int getRemainingPack() {
			return remainingSlots;
	}
	
	public void decrementRemainingSlots(){
		if(remainingSlots>0){
		remainingSlots--;
		
		/*
		 * 
		 * si le nombre de slots restant est divisible 
		 * par la longueur du packet alors on décrémente le 
		 * nombre de packets restants
		 * 
		 * 
		 */
		
		if(remainingSlots%packLength==0){
		remainingPackets--;	
		}
		
		N=0;
		this.repaint();
		}
	}
	
	public void onEraseConfig(){
		N=0;
		bo=0;
		bornSup = 0;
		remainingSlots=0;
		remainingPackets=0;
		crash=false;
		sending=false;
		restorePoints.clear();
	    this.repaint();
	}
	
	public void onCrashConfig(){
			N++;
			
			/*
			 * rejeter le packet si N==16
			 * 
			 */
			
			if(N==16){
				
			}else {
			
				
				/*
				 * on teste si on est dans le cas d'un exercice saisi
				 * par l'utilisateur ou une simulation normale 
				 * 
				 */
				//TODO
				
			if(exercice){
				
			}else{
				Random randBo=new Random();
				bornSup = (int) (Math.pow(2, Math.min(N, 10))-1);
				bo=randBo.nextInt(bornSup);
			}
			
			
			}
	}
	
	public void setCrash(boolean crash) {
		this.crash = crash;
		this.repaint();
	}
	
	public void decrementBackOff(){
		if(bo>0){
			bo--;
			this.repaint();
		}
	}
	
	public void incrementBackOffUrgentCase(int x){
		bo+=x;
		this.repaint();
	}
	
	public int getBo() {
		return bo;
	}
	
	public String getoName() {
		return ordiName;
	}
	
	public static void delete(){
		nameSet--;	
	}

	public static void resetParam(){
		nameSet='A';
	}

	@Override
	public void keyPressed(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyReleased(KeyEvent a) {
		// TODO Auto-generated method stub
		
		TextField tf=(TextField) a.getSource();
		
		if (tf==packetsTextField) {
			try {

				remainingPackets = Math.abs(Integer.parseInt(packetsTextField
						.getText()));
			} catch (NumberFormatException e) {

				if (!packetsTextField.getText().isEmpty()) {
					remainingPackets = 0;
					packetsTextField.setText(null);
				} else
					;

			}
			remainingSlots = remainingPackets * packLength;
		}else if(tf==backoffTextField){
			try {
				
				bo=Math.abs(Integer.parseInt(backoffTextField.getText()));
			} catch (NumberFormatException e) {
				
				if(!backoffTextField.getText().isEmpty()){
				bo=0;
				backoffTextField.setText(null);
				}else ;
				
			}
		}else;
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		if(e.getClickCount()==2){
			
			/*
			 * on teste si le nombre de packets est suffisant pour 
			 * entamer la simulation 
			 * au moins un packet 
			 */
			if(remainingPackets>0){
				/*
				 * si c'est le cas 
				 * on initialise le tableau de valeurs 
				 * on inhibe la saisie dans le textfield du nombre de 
				 * packets 
				 * et on affiche l'interface de saisie 
				 */
				
				new ExerciceDialog(remainingPackets);
				
			System.out.println("double");	
			}else{
			Warning.warningInformation("Please add some Packets, \n","404");	
			}
			
		}else;
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void focusGained(FocusEvent a) {
			try{
				TextField tf=(TextField)a.getSource();
				tf.selectAll();
			}catch(Exception e){
				
			}
	}

	@Override
	public void focusLost(FocusEvent a) {
		try{
			TextField tf=(TextField)a.getSource();
			tf.select(0,0);
		}catch(Exception e){
			
		}
	}
	
	
}

